#include "sm_state_machine.h"

#include "stdio.h"


//状态转移表
static int SM_STATE_TRANSITION_TABLE[SM_EVENT_MAX+1][SM_STATE_MAX+1]=
{
    {-1,0,1,2,3,4,5},
    {0,2,2,2,2,2,2},
    {1,1,1,1,1,1,1},
    {2,-1,-1,4,4,4,-1},
    {3,-1,-1,-1,-1,5,-1},
    {4,-1,-1,-1,-1,4,4},
    {5,-1,-1,-1,-1,3,-1},
    {6,0,0,0,0,0,0}
};

//状态错误检查表
//0:可以接受该状态
//not 0:不可接受该状态
static int SM_STATE_ERROR_CHECK_TABLE[SM_EVENT_MAX+1][SM_STATE_MAX+1]=
{
    {-1,0,1,2,3,4,5},
    {0,0,0,0,0,0,0},
    {1,0,0,0,0,0,0},
    {2,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,0,0,0,SM4A_PRECONDITION_ERROR},
    {3,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,0,SM4A_PRECONDITION_ERROR},
    {4,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,0,0},
    {5,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,SM4A_PRECONDITION_ERROR,0,SM4A_PRECONDITION_ERROR},
    {6,0,0,0,0,0,0}
};

//当前状态机
static SM_STATE_MACHINE_STRUCT state_machine =
{
    SM_STATE_TERMINATED,
    nullptr,
    nullptr
};

//
static int index = 0;

//枚举转字符串
const char * type2str(IN SM_STATE_ENUM state)
{
    const char *str="";
    switch (state) {
    case SM_STATE_ERROR:
        str="SM_STATE_ERROR";
        break;
    case SM_STATE_TERMINATED:
        str="SM_STATE_TERMINATED";
        break;
    case SM_STATE_IDLE:
        str="SM_STATE_IDLE";
        break;
    case SM_STATE_QUEUE_EMPTY:
        str="SM_STATE_QUEUE_EMPTY";
        break;
    case SM_STATE_QUEUE_PARTY_FULL:
        str="SM_STATE_QUEUE_PARTY_FULL";
        break;
    case SM_STATE_QUEUE_FULL:
        str="SM_STATE_QUEUE_FULL";
        break;
    default:
        str="inValid";
        break;
    }

    return str;
}

const char * type2str(IN SM_EVENT_ENUM event)
{
    const char *str="";
    switch (event) {
    case SM_EVENT_INITIALIZE:
        str="SM_EVENT_INITIALIZE";
        break;
    case SM_EVENT_TERMINATE:
        str="SM_EVENT_TERMINATE";
        break;
    case SM_EVENT_QUEUE:
        str="SM_EVENT_QUEUE";
        break;
    case SM_EVENT_QUEUE_FULL:
        str="SM_EVENT_QUEUE_FULL";
        break;
    case SM_EVENT_GET_RESULT:
        str="SM_EVENT_GET_RESULT";
        break;
    case SM_EVENT_GET_RESULT_EMPTY:
        str="SM_EVENT_GET_RESULT_EMPTY";
        break;
    case SM_EVENT_ERROR:
        str="SM_EVENT_ERROR";
        break;
    default:
        str="inValid";
        break;
    }
    return str;
}

int sm_state_machine_create()
{
    int iResult = OK;
    printf("%s > ()\n",__func__);

    cout<<"index="<<index<<",current state="<<type2str(state_machine.sm_current_state)<<endl;

    if(state_machine.sm_transition_table_p != nullptr)
    {
        state_machine.sm_transition_table_p = nullptr;
        state_machine.sm_transition_table_p = &SM_STATE_TRANSITION_TABLE;
    }else
    {
        state_machine.sm_transition_table_p = &SM_STATE_TRANSITION_TABLE;
    }

    if(state_machine.sm_error_check_table_p != nullptr)
    {
        state_machine.sm_error_check_table_p = nullptr;
        state_machine.sm_error_check_table_p = &SM_STATE_ERROR_CHECK_TABLE;
    }else
    {
        state_machine.sm_error_check_table_p = &SM_STATE_ERROR_CHECK_TABLE;
    }
    state_machine.sm_current_state = SM_STATE_TERMINATED;
//    cout<<(*state_machine.sm_error_check_table_p)[2+1][0+1]<<endl;

//    cout<<SM_STATE_ERROR_CHECK_TABLE[SM_EVENT_ERROR+1][SM_STATE_QUEUE_FULL+1];

    printf("%s < () = 0x%x\n",__func__,iResult);
    return iResult;
}

int sm_state_machine_destory()
{
    int iResult = OK;
    printf("%s > ()\n",__func__);

    if(state_machine.sm_transition_table_p != nullptr)
    {
        state_machine.sm_transition_table_p = nullptr;
    }

    if(state_machine.sm_error_check_table_p != nullptr)
    {
        state_machine.sm_error_check_table_p = nullptr;
    }
    printf("%s < () = 0x%x\n",__func__,iResult);
    return iResult;
}

int sm_state_machine_check_transition(SM_EVENT_ENUM event, int *state_check_result)
{
    int iResult = OK;
    printf("%s > ()\n",__func__);

    //1.检查各种参数是否满足要求
    if(state_check_result == nullptr)
    {
        iResult = SM4A_NULL_POINTER_ERROR;
    }
    if(iResult == OK)
    {
        if(state_machine.sm_transition_table_p == nullptr)
        {
            iResult = SM4A_STATE_MACHINE_NOT_CREATED_ERROR;
        }
    }
    if(iResult == OK)
    {
        if(state_machine.sm_error_check_table_p == nullptr)
        {
            iResult = SM4A_STATE_MACHINE_NOT_CREATED_ERROR;
        }
    }
    if(iResult == OK)
    {
        if(event <= SM_EVENT_MIN || event >= SM_EVENT_MAX)
        {
            iResult = SM4A_ST_PARAMETERS_ERROR;
        }
    }

    SM_STATE_ENUM current_state = state_machine.sm_current_state;

    //2.查看状态转移图检查结果
    if(iResult == OK)
    {
        *state_check_result = (*state_machine.sm_error_check_table_p)[event+1][current_state+1];
    }

    printf("%s, (current_state=%s,event=%s,*state_check_result=0x%x)\n",
           __func__,type2str(current_state),type2str(event),*state_check_result);

    printf("%s < () = 0x%x\n",__func__,iResult);
    return iResult;
}

int sm_state_machine_perform_transition(SM_EVENT_ENUM event)
{
    int iResult = OK;
    printf("%s > ()\n",__func__);

    //1.检查各种参数是否满足要求
    if(iResult == OK)
    {
        if(state_machine.sm_transition_table_p == nullptr)
        {
            iResult = SM4A_STATE_MACHINE_NOT_CREATED_ERROR;
        }
    }
    if(iResult == OK)
    {
        if(state_machine.sm_error_check_table_p == nullptr)
        {
            iResult = SM4A_STATE_MACHINE_NOT_CREATED_ERROR;
        }
    }
    if(iResult == OK)
    {
        if(event <= SM_EVENT_MIN || event >= SM_EVENT_MAX)
        {
            iResult = SM4A_ST_PARAMETERS_ERROR;
        }
    }

    SM_STATE_ENUM current_state = state_machine.sm_current_state;
    int after_state_tmp = -3;
    SM_STATE_ENUM after_state = SM_STATE_MIN;
    //2.查看状态转移图检查结果
    if(iResult == OK)
    {
        after_state_tmp = (*state_machine.sm_transition_table_p)[event+1][current_state+1];
    }

    //3.将int转换成enum
    if(iResult == OK)
    {
        if(after_state_tmp < SM_STATE_MIN || after_state_tmp>SM_STATE_MAX)
        {
            iResult = SM4A_ST_SYSTEM_ERROR;
        }else
        {
            after_state = (SM_STATE_ENUM)after_state_tmp;
            state_machine.sm_current_state = after_state;
        }
    }

    index++;
    printf("%s, (index=%d,current_state=%s,event=%s,after_state=%s)\n",
           __func__,index,type2str(current_state),type2str(event),type2str(after_state));

    printf("%s < () = 0x%x\n",__func__,iResult);
    return iResult;
}
